﻿using PowerTriggers.Properties;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using PowerTriggers.ServiceReference;
using System.Threading;
using System.ServiceModel;
using System.ServiceProcess;
using System.Linq;
using System.Security.Principal;

namespace PowerTriggers
{
    public class ProgramContext : ApplicationContext
    {
        private IContainer components;
        private MenuItem exitContextMenuItem;
        internal bool AutoHide = true;
        private frmMain mainForm;
        private NotifyIcon mainNotifyIcon;
        private ContextMenu mainNotifyIconContextMenu;
        private MenuItem showContextMenuItem;
        private static volatile bool abandonDummyThread;

        public ProgramContext()
        {
            abandonDummyThread = false;
            this.InitializeContext();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "PowerTriggers.EventLogHelper.LogInformation(System.String)")]
        public ProgramContext(string[] args)
            : this()
        {
            try
            {
                //EventLogHelper.LogInformation("Application started");

                bool argShow = (args != null && args.Where(arg => arg.ToLower() == "/show").Any());
                bool argHide = (args != null && args.Where(arg => arg.ToLower() == "/hide").Any());
                bool argFirstRun = (args != null && args.Where(arg => arg.ToLower() == "/firstrun").Any());

                if (!argHide && (argShow || argFirstRun || Settings.Default.AlwaysOnTop))
                {
                    ShowForm(false, argFirstRun);
                }
                else
                {
                    abandonDummyThread = true;
                    //// The first time that a client connection is opened is very slow, so open 
                    //// one immediately, on a background thread.  This will make first-time opening of frmMain
                    //// much quicker
                    //ThreadStart start = new ThreadStart(OpenDummyClients);
                    //Thread thread = new Thread(start);
                    //thread.IsBackground = true; // make sure this thread does not block the process from exiting
                    //thread.Priority = ThreadPriority.BelowNormal;
                    //thread.Start();
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Error occurred when trying to start Power Triggers: " + ex.Message, "Power Triggers", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "dummy")]
        private static void OpenDummyClients()
        {
            try
            {
                if (!abandonDummyThread)
                {
                    WcfClientFactory.EnsureWindowsServiceIsRunning(WcfClientFactory.CurrentServerName);
                }
            }
            catch (System.Exception ex)
            {
                EventLogHelper.LogError("OpenDummyClients.ServiceCheck Error", ex);
            }

            try
            {
                if (!abandonDummyThread)
                {
                    using (PowerTriggersWcfClient serviceClient = WcfClientFactory.OpenWcfClient())
                    {
                        if (!abandonDummyThread)
                        {
                            serviceClient.Open();
                        }
                        if (!abandonDummyThread)
                        {
                            var dummy = serviceClient.GetData();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                EventLogHelper.LogError("OpenDummyClients.PowerTriggersWcfClient Error", ex);
            }

            try
            {
                if (!abandonDummyThread)
                {
                    DummayCallback dummyCallback = new DummayCallback();
                    InstanceContext context = new InstanceContext(dummyCallback);
                    using (PowerTriggersWcfCallbackClient client = new PowerTriggersWcfCallbackClient(context))
                    {
                        if (!abandonDummyThread)
                        {
                            client.Open();
                        }
                        if (!abandonDummyThread)
                        {
                            client.SubscribeHistoryChangedEvent();
                            client.UnsubscribeHistoryChangedEvent();
                        }
                    }
                }
            }
            catch (System.Exception ex)
            {
                EventLogHelper.LogError("OpenDummyClients.PowerTriggersWcfCallbackClient Error", ex);
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "exitContextMenuItem"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "mainForm"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "mainNotifyIcon"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "mainNotifyIconContextMenu"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "showContextMenuItem")]
        protected override void Dispose(bool disposing)
        {
            abandonDummyThread = true;
            if (this.mainForm != null)
            {
                this.mainForm.Dispose();
                this.mainForm = null;
            }
            if (disposing && (this.components != null))
            {
                this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void ExitThreadCore()
        {
            abandonDummyThread = true;
            if (this.mainForm != null)
            {
                this.mainForm.Dispose();
                this.mainForm = null;
            }
            base.ExitThreadCore();
        }

        private void exitContextMenuItem_Click(object sender, EventArgs e)
        {
            abandonDummyThread = true;
            ExitApplication();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "PowerTriggers.EventLogHelper.LogInformation(System.String)")]
        internal void ExitApplication()
        {
            abandonDummyThread = true;
            if (this.mainForm != null)
            {
                this.mainForm.Dispose();
                this.mainForm = null;
            }
            //EventLogHelper.LogInformation("Exiting application");
            base.ExitThread();
        }

        private void InitializeContext()
        {
            this.components = new Container();
            this.mainNotifyIcon = new NotifyIcon(this.components);
            this.mainNotifyIconContextMenu = new ContextMenu();
            this.showContextMenuItem = new MenuItem();
            this.exitContextMenuItem = new MenuItem();
            this.mainNotifyIcon.ContextMenu = this.mainNotifyIconContextMenu;
            this.mainNotifyIcon.Click += new EventHandler(this.mainNotifyIcon_Click);
            this.mainNotifyIcon.Icon = Resources.ApplicationIcon16x16;
            this.mainNotifyIcon.Text = "Power Triggers";
            this.mainNotifyIcon.Visible = true;
            this.mainNotifyIconContextMenu.MenuItems.AddRange(new MenuItem[] { this.showContextMenuItem, this.exitContextMenuItem });
            this.showContextMenuItem.Index = 0;
            this.showContextMenuItem.Text = "&Show";
            this.showContextMenuItem.DefaultItem = true;
            this.showContextMenuItem.Click += new EventHandler(this.showContextMenuItem_Click);
            this.exitContextMenuItem.Index = 1;
            this.exitContextMenuItem.Text = "&Exit";
            this.exitContextMenuItem.Click += new EventHandler(this.exitContextMenuItem_Click);
        }

        private void mainForm_Closed(object sender, EventArgs e)
        {
            this.mainForm.Dispose();
            this.mainForm = null;
        }

        private void mainNotifyIcon_Click(object sender, EventArgs e)
        {
            if (((MouseEventArgs)e).Button == MouseButtons.Left)
            {
                this.ShowForm(true, false);
            }
        }

        private void showContextMenuItem_Click(object sender, EventArgs e)
        {
            this.ShowForm(true, false);
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "activate")]
        private void ShowForm(bool activate, bool firstRun)
        {
            try
            {
                abandonDummyThread = true;
                Cursor.Current = Cursors.WaitCursor;
                if (this.mainForm == null)
                {
                    this.mainForm = new frmMain(this, firstRun);
                    this.mainForm.Show();
                    this.mainForm.Closed += new EventHandler(this.mainForm_Closed);
                }
                else
                {
                    this.mainForm.Visible = true;
                }
                this.mainForm.Activate();
            }
            catch (System.Exception ex)
            {
                Cursor.Current = Cursors.Default;
                MessageBox.Show("Error: " + ex.Message, "Power Triggers", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        internal void HideForm()
        {
            if (!Settings.Default.AlwaysOnTop)
            {
                if (this.mainForm != null)
                {
                    this.mainForm.Hide();
                }
            }
        }
    }
}
